import React, { useEffect } from "react";
import type { ReactNode } from "react";
import {
  Menu,
  MenuItem,
  Divider,
  ListItemIcon,
  ListItemText,
} from "@mui/material";

// 为全局 Window 接口添加自定义属性
declare global {
  interface Window {
    lastContextMenuPosition?: { x: number; y: number };
    lastTouchPosition?: { x: number; y: number };
    contextMenuClipboard?: string; // 文本剪贴板
    contextMenuImageClipboard?: string; // 图片剪贴板URL
    _hasClipboardContent?: boolean; // 剪贴板内容标记
    _clipboardImageType?: string; // 剪贴板图片类型标记
    _lastPastedImageUrl?: string; // 上次粘贴图片的URL
    _lastPastedImageHash?: string; // 上次粘贴图片的哈希
  }
}

export interface ContextMenuItem {
  /**
   * 菜单项的唯一标识
   */
  id: string;

  /**
   * 菜单项的显示文本
   */
  label: string;

  /**
   * 菜单项的图标（可选）
   */
  icon?: ReactNode;

  /**
   * 点击菜单项时的回调函数
   */
  onClick: () => void;

  /**
   * 菜单项的颜色（可选），用于强调或警告
   */
  color?:
    | "primary"
    | "secondary"
    | "error"
    | "warning"
    | "info"
    | "success"
    | "inherit";

  /**
   * 是否在此菜单项后添加分隔线
   */
  divider?: boolean;

  /**
   * 是否禁用此菜单项
   */
  disabled?: boolean;
}

export interface ContextMenuProps {
  /**
   * 菜单项配置数组
   */
  items: ContextMenuItem[];

  /**
   * 菜单是否打开
   */
  open: boolean;

  /**
   * 关闭菜单的回调函数
   */
  onClose: () => void;

  /**
   * 菜单位置 X 坐标
   */
  positionX: number;

  /**
   * 菜单位置 Y 坐标
   */
  positionY: number;
}

/**
 * 上下文菜单组件
 *
 * 基于 Material-UI 的 Menu 组件实现的右键菜单
 * 支持自定义菜单项、图标和分隔线
 * @author BelovedLYC
 */
const ContextMenu: React.FC<ContextMenuProps> = ({
  items,
  open,
  onClose,
  positionX,
  positionY,
}) => {
  // 优先使用全局存储的位置信息
  const position = window.lastContextMenuPosition || {
    x: positionX,
    y: positionY,
  };

  // 创建菜单项数组，不使用 Fragment
  const menuItems = [];

  // 遍历菜单项，生成 MenuItem 和 Divider 元素
  for (let i = 0; i < items.length; i++) {
    const item = items[i];

    // 添加菜单项
    menuItems.push(
      <MenuItem
        key={item.id || `item-${i}`}
        onClick={() => {
          item.onClick();
          onClose();
        }}
        disabled={item.disabled}
        sx={{
          color: item.color ? `${item.color}.main` : "inherit",
          py: 1,
          px: 2,
          // 确保不会应用高亮背景，只使用默认的hover效果
          backgroundColor: "transparent !important",
          "&:hover": {
            backgroundColor: (theme) =>
              theme.palette.mode === "dark"
                ? "rgba(255,255,255,0.08) !important"
                : "rgba(0,0,0,0.04) !important",
          },
        }}
      >
        {item.icon && (
          <ListItemIcon sx={{ color: "inherit" }}>{item.icon}</ListItemIcon>
        )}
        <ListItemText
          primary={item.label}
          primaryTypographyProps={{
            variant: "body2",
            sx: { fontWeight: 500 },
          }}
        />
      </MenuItem>
    );

    // 如果需要分隔线，添加分隔线
    if (item.divider && i < items.length - 1) {
      menuItems.push(<Divider key={`divider-${i}`} />);
    }
  }

  return (
    <Menu
      open={open}
      onClose={onClose}
      anchorReference="anchorPosition"
      anchorPosition={{ top: position.y, left: position.x }}
      elevation={3}
      sx={{
        "& .MuiPaper-root": {
          borderRadius: "8px",
          minWidth: "200px",
          boxShadow: "0 4px 20px rgba(0,0,0,0.1)",
          border: "1px solid",
          borderColor: (theme) =>
            theme.palette.mode === "dark"
              ? "rgba(255,255,255,0.1)"
              : "rgba(0,0,0,0.05)",
        },
      }}
    >
      {menuItems}
    </Menu>
  );
};

/**
 * 创建上下文菜单事件处理器
 *
 * 用于处理右键点击事件，返回菜单位置和打开状态
 * 支持全局右键菜单和复制粘贴功能
 */
export const useContextMenu = (options?: {
  /**
   * 是否启用全局右键菜单
   * 设置为 true 时将监听整个文档的右键事件
   */
  global?: boolean;

  /**
   * 指定要监听右键事件的元素引用
   * 当不需要监听整个文档时，可以指定特定元素
   */
  targetRef?: React.RefObject<HTMLElement>;

  /**
   * 自定义处理选中文本的逻辑
   * 返回 true 表示已处理，将不再执行默认复制逻辑
   */
  onTextSelected?: (selectedText: string) => boolean;

  /**
   * 自定义处理图片的逻辑
   * 返回 true 表示已处理，将不再执行默认复制逻辑
   */
  onImageSelected?: (
    imageElement: HTMLImageElement,
    imageUrl: string
  ) => boolean;
}) => {
  const [contextMenu, setContextMenu] = React.useState<{
    mouseX: number;
    mouseY: number;
    open: boolean;
    selectedText?: string;
    selectedImage?: {
      element: HTMLImageElement;
      src: string;
    };
  }>({
    mouseX: 0,
    mouseY: 0,
    open: false,
  });

  const handleContextMenu = (
    event:
      | React.MouseEvent
      | {
          clientX: number;
          clientY: number;
          preventDefault: () => void;
          stopPropagation: () => void;
          target?: EventTarget | null;
        }
  ) => {
    // 阻止默认右键菜单
    if (event && typeof event.preventDefault === "function") {
      event.preventDefault();
    }

    // 阻止事件冒泡
    if (event && typeof event.stopPropagation === "function") {
      event.stopPropagation();
    }

    // 获取鼠标位置
    const mouseX = event.clientX;
    const mouseY = event.clientY;

    // 检查是否有选中文本
    const selectedText = window.getSelection()?.toString() || "";

    // 检查是否右键点击了图片
    let selectedImage = undefined;
    if (event.target instanceof HTMLImageElement) {
      selectedImage = {
        element: event.target,
        src: event.target.src,
      };
    } else if (event.target instanceof Element) {
      // 检查父元素是否有图片
      const img = event.target.closest("img");
      if (img instanceof HTMLImageElement) {
        selectedImage = {
          element: img,
          src: img.src,
        };
      }
    }

    console.log("打开上下文菜单:", {
      mouseX,
      mouseY,
      selectedText,
      selectedImage: selectedImage?.src,
      event,
    });

    // 保存位置到全局变量
    window.lastContextMenuPosition = { x: mouseX, y: mouseY };

    // 更新状态
    setContextMenu({
      mouseX,
      mouseY,
      open: true,
      selectedText,
      selectedImage,
    });
  };

  const closeContextMenu = () => {
    console.log("关闭上下文菜单");

    // 重置状态
    setContextMenu({
      mouseX: 0,
      mouseY: 0,
      open: false,
    });
  };

  // 复制功能
  const handleCopy = () => {
    // 优先处理文本
    const selectedText =
      contextMenu.selectedText || window.getSelection()?.toString();
    if (selectedText) {
      navigator.clipboard.writeText(selectedText).then(
        () => {
          console.log("文本已复制到剪贴板:", selectedText);
          // 同时保存到全局变量用于内部粘贴
          window.contextMenuClipboard = selectedText;
          // 清除图片剪贴板
          window.contextMenuImageClipboard = undefined;
        },
        (err) => {
          console.error("复制失败:", err);
        }
      );
      return;
    }

    // 如果没有选中文本，尝试复制图片
    if (contextMenu.selectedImage) {
      const imageUrl = contextMenu.selectedImage.src;

      // 保存图片URL到全局变量，用于内部粘贴
      window.contextMenuImageClipboard = imageUrl;
      window.contextMenuClipboard = undefined; // 清除文本剪贴板

      // 设置一个标记，表示剪贴板有内容
      window._hasClipboardContent = true;

      console.log("图片已复制到剪贴板:", imageUrl);

      // 尝试将图片复制到系统剪贴板 (支持度有限)
      try {
        // 避免直接使用canvas处理带有跨域限制的图片
        // 而是提供一个特殊标记，表明这是一个URL，而非实际图片数据
        window._clipboardImageType = "url";

        // 对于没有跨域限制的图片，尝试获取实际图片数据
        const img = new Image();
        img.crossOrigin = "anonymous";

        // 添加超时处理
        const timeoutId = setTimeout(() => {
          console.log("图片加载超时，仅保存URL");
          window._clipboardImageType = "url";
        }, 2000);

        img.onload = function () {
          clearTimeout(timeoutId);

          try {
            const canvas = document.createElement("canvas");
            const ctx = canvas.getContext("2d");
            canvas.width = img.width;
            canvas.height = img.height;
            ctx?.drawImage(img, 0, 0);

            // 尝试获取图片数据
            canvas.toBlob((blob) => {
              if (blob && navigator.clipboard.write) {
                const item = new ClipboardItem({ "image/png": blob });
                navigator.clipboard.write([item]).then(
                  () => {
                    console.log("图片已复制到系统剪贴板");
                    window._clipboardImageType = "blob";
                  },
                  (err) => console.error("复制图片到系统剪贴板失败:", err)
                );
              }
            }, "image/png");
          } catch (error) {
            console.warn("无法复制图片数据，仅保存URL", error);
          }
        };

        img.onerror = function () {
          clearTimeout(timeoutId);
          console.log("无法加载图片用于复制，仅保存URL");
          window._clipboardImageType = "url";
        };

        // 为了减少跨域问题，可以尝试添加代理或随机参数
        if (imageUrl.startsWith("http")) {
          // 添加随机参数避免缓存引起的跨域问题
          img.src = `${imageUrl}${
            imageUrl.includes("?") ? "&" : "?"
          }cacheBust=${Date.now()}`;
        } else {
          img.src = imageUrl;
        }
      } catch (error) {
        console.warn("系统不支持图片复制到剪贴板:", error);
      }
    }
  };

  // 粘贴功能
  const handlePaste = async () => {
    try {
      // 优先检查内部图片剪贴板
      if (window.contextMenuImageClipboard) {
        return {
          type: "image",
          data: window.contextMenuImageClipboard,
        };
      }

      // 优先使用系统剪贴板API
      if (navigator.clipboard) {
        try {
          // 尝试读取系统剪贴板中的图片
          if (navigator.clipboard.read) {
            const clipboardItems = await navigator.clipboard.read();

            for (const clipboardItem of clipboardItems) {
              // 检查是否有图片类型
              if (
                clipboardItem.types.some((type) => type.startsWith("image/"))
              ) {
                for (const type of clipboardItem.types) {
                  if (type.startsWith("image/")) {
                    const blob = await clipboardItem.getType(type);
                    const url = URL.createObjectURL(blob);
                    return {
                      type: "image",
                      data: url,
                      blob,
                    };
                  }
                }
              }
            }
          }

          // 如果没有图片，尝试读取文本
          const clipboardText = await navigator.clipboard.readText();
          return {
            type: "text",
            data: clipboardText || window.contextMenuClipboard || "",
          };
        } catch (error) {
          console.warn("无法访问系统剪贴板:", error);
        }
      }

      // 返回内部存储的文本
      return {
        type: "text",
        data: window.contextMenuClipboard || "",
      };
    } catch (error) {
      console.error("粘贴操作失败:", error);
      return { type: "error", error };
    }
  };

  // 全局右键菜单支持
  useEffect(() => {
    const targetElement =
      options?.targetRef?.current || (options?.global ? document : null);

    if (!targetElement) return;

    const handleGlobalContextMenu = (e: Event) => {
      if (!(e instanceof MouseEvent)) return;

      // 检查是否有选中文本
      const selectedText = window.getSelection()?.toString() || "";

      // 检查是否点击了图片
      let targetImage = null;
      if (e.target instanceof HTMLImageElement) {
        targetImage = e.target;
      } else if (e.target instanceof Element) {
        const img = e.target.closest("img");
        if (img instanceof HTMLImageElement) {
          targetImage = img;
        }
      }

      // 如果提供了自定义处理选中文本的逻辑且已处理，则不再执行默认逻辑
      if (
        selectedText &&
        options?.onTextSelected &&
        options.onTextSelected(selectedText)
      ) {
        return;
      }

      // 如果提供了自定义处理图片的逻辑且已处理，则不再执行默认逻辑
      if (
        targetImage &&
        options?.onImageSelected &&
        options.onImageSelected(targetImage, targetImage.src)
      ) {
        return;
      }

      // 打开上下文菜单
      handleContextMenu({
        clientX: e.clientX,
        clientY: e.clientY,
        preventDefault: () => e.preventDefault(),
        stopPropagation: () => e.stopPropagation(),
        target: e.target,
      });
    };

    targetElement.addEventListener("contextmenu", handleGlobalContextMenu);

    return () => {
      targetElement.removeEventListener("contextmenu", handleGlobalContextMenu);
    };
  }, [
    options?.global,
    options?.targetRef,
    options?.onTextSelected,
    options?.onImageSelected,
  ]);

  return {
    open: contextMenu.open,
    positionX: contextMenu.mouseX,
    positionY: contextMenu.mouseY,
    selectedText: contextMenu.selectedText,
    selectedImage: contextMenu.selectedImage,
    handleContextMenu,
    closeContextMenu,
    copyText: handleCopy,
    pasteText: handlePaste,
    hasSelectedContent:
      !!contextMenu.selectedText || !!contextMenu.selectedImage,
  };
};

export default ContextMenu;
